package ynu.edu.rule;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.DefaultResponse;
import org.springframework.cloud.client.loadbalancer.EmptyResponse;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.client.loadbalancer.Response;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

public class DynamicStrategyLoadBalancer implements ReactorServiceInstanceLoadBalancer {

    private final String serviceId;
    private final ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
    private final AtomicInteger instanceIndex = new AtomicInteger(0);
    private final Random random = new Random();

    public DynamicStrategyLoadBalancer(
            ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,
            String serviceId) {
        this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
        this.serviceId = serviceId;
    }

    @Override
    public Mono<Response<ServiceInstance>> choose(Request request) {
        return Mono.defer(() -> {
            ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable();
            if (supplier == null) {
                return Mono.empty();
            }
            return supplier.get().next().map(this::getDynamicStrategyResponse);
        });
    }

    private Response<ServiceInstance> getDynamicStrategyResponse(List<ServiceInstance> instances) {
        if (instances.isEmpty()) {
            return new EmptyResponse();
        }
        int instanceCount = instances.size();
        // 根据实例数量选择策略
        if (instanceCount > 3) {
            return getRandomResponse(instances);
        } else {
            return getRoundRobinResponse(instances);
        }
    }

    // 随机策略
    private Response<ServiceInstance> getRandomResponse(List<ServiceInstance> instances) {
        int randomIndex = random.nextInt(instances.size());
        ServiceInstance selectedInstance = instances.get(randomIndex);
        return new DefaultResponse(selectedInstance);
    }

    // 轮询策略
    private Response<ServiceInstance> getRoundRobinResponse(List<ServiceInstance> instances) {
        int index = instanceIndex.getAndIncrement() % instances.size();
        ServiceInstance selectedInstance = instances.get(index);
        return new DefaultResponse(selectedInstance);
    }

    @Override
    public Mono<Response<ServiceInstance>> choose() {
        return ReactorServiceInstanceLoadBalancer.super.choose();
    }
}